{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import xarray as xr\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<xarray.Dataset>\n",
       "Dimensions:  (lat: 720, lon: 1440, period: 2, time: 276)\n",
       "Coordinates:\n",
       "  * time     (time) datetime64[ns] 1993-01-15 1993-02-15 1993-03-15 ...\n",
       "  * period   (period) float32 1.0 0.5\n",
       "  * lat      (lat) float32 -89.875 -89.625 -89.375 -89.125 -88.875 -88.625 ...\n",
       "  * lon      (lon) float32 0.125 0.375 0.625 0.875 1.125 1.375 1.625 1.875 ...\n",
       "Data variables:\n",
       "    ampl     (lat, lon, period) float32 ...\n",
       "    phase    (lat, lon, period) float32 ...\n",
       "Attributes:\n",
       "    title:                      Mean Sea Level changes amplitude and phases\n",
       "    institution:                ESA, CLS, CNES\n",
       "    references:                 http://www.esa-sealevel-cci.org/products\n",
       "    tracking_id:                \n",
       "    source:                     ERS-1 Phase C OPR V6, ERS-1 Phase E OPR V3, E...\n",
       "    platform:                   ERS-1, ERS-2, ENVISAT, TOPEX/Poseidon, Jason-...\n",
       "    sensor:                     RA, RA2, Poseidon-1, Poseidon-2, Poseidon-3, ...\n",
       "    Conventions:                CF-1.6\n",
       "    product_version:            2.0\n",
       "    summary:                    This dataset contains global maps of mean sea...\n",
       "    keywords:                   altimetry\n",
       "    id:                         GLO-MSL-AMPH-MERGED\n",
       "    naming_authority:           ESA CCI\n",
       "    keywords_vocabulary:        NetCDF COARDS Climate and Forecast Standard N...\n",
       "    standard_name_vocabulary:   NetCDF Climate and Forecast (CF) Metadata Con...\n",
       "    cdm_data_type:              Grid\n",
       "    comment:                    These data were produced at CLS as part of th...\n",
       "    license:                    ESA CCI Data Policy: free and open access.\n",
       "    date_created:               2016-12-02 00:00:00\n",
       "    history:                    2016-12-02 00:00:00 : creation\n",
       "    contact:                    info-sealevel@esa-sealevel-cci.org\n",
       "    project:                    Climate Change Initiative - European Space Ag...\n",
       "    creator_name:               ESA, CLS\n",
       "    creator_url:                http://www.esa-sealevel-cci.org/\n",
       "    creator_email:              info-sealevel@esa-sealevel-cci.org\n",
       "    geospatial_lat_min:         -89.875\n",
       "    geospatial_lat_max:         89.875\n",
       "    geospatial_lon_min:         0.125\n",
       "    geospatial_lon_max:         359.875\n",
       "    geospatial_vertical_min:    0.0\n",
       "    geospatial_vertical_max:    0.0\n",
       "    geospatial_lat_units:       degrees_north\n",
       "    geospatial_lon_units:       degrees_east\n",
       "    geospatial_lat_resolution:  0.25\n",
       "    geospatial_lon_resolution:  0.25\n",
       "    time_coverage_start:        1993-01-01 00:00:00\n",
       "    time_coverage_end:          2015-12-31 23:59:59\n",
       "    time_coverage_duration:     P23Y\n",
       "    time_coverage_resolution:   P1M"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds0 = xr.open_dataset(\"C:\\\\Users\\\\Norman\\\\.cate\\\\data_stores\\\\local\\\\local.esacci.SEALEVEL.mon.IND.MSLAMPH.multi-sensor.multi-platform.MERGED.2-0.r1.6ba656f9-7c90-3b15-aad2-c137f8b61909\\\\ESACCI-SEALEVEL-IND-MSLAMPH-MERGED-20161202000000-fv02.nc\")\n",
    "ds0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds0['phase'] is ds0['phase']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "We observe **two issues** here which make it hard to work with this data in the current version of Cate:\n",
    "\n",
    "1. Cate can only display dataset variables whose *last* dimensions are `lat` and `lon`, in this order;\n",
    "2. there is a dimension and coordinate variable `time`, which is not used by any data variable. Instead it seems, it provides the individual time steps of the data within the temporal coverage that was used to produce the dataset. If we want to concatenate multiple Sea-Level datasets to form a time series, this will later on fail, because Cate interprets the `time` as an axis as defined by the [CF-Conventions](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/build/ch05.html#idp6750288).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "We address the first the 2nd issue by simply renaming the `time` variable into `time_step` using the [xarray](http://xarray.pydata.org) [Dataset](http://xarray.pydata.org/en/stable/data-structures.html#dataset) method [rename()](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.rename.html):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<xarray.DataArray 'time_step' (time_step: 276)>\n",
       "array(['1993-01-15T00:00:00.000000000', '1993-02-15T00:00:00.000000000',\n",
       "       '1993-03-15T00:00:00.000000000', ..., '2015-10-15T00:00:00.000000000',\n",
       "       '2015-11-15T00:00:00.000000000', '2015-12-15T00:00:00.000000000'],\n",
       "      dtype='datetime64[ns]')\n",
       "Coordinates:\n",
       "  * time_step  (time_step) datetime64[ns] 1993-01-15 1993-02-15 1993-03-15 ...\n",
       "Attributes:\n",
       "    long_name:      time\n",
       "    standard_name:  time"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds = ds0.rename(time='time_step')\n",
    "ds.time_step"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "Then we add the `time` and `time_bnds` coordinate variables using the [xarray](http://xarray.pydata.org) [Dataset](http://xarray.pydata.org/en/stable/data-structures.html#dataset) method [assign_coords()](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.assign_coords.html) according to the CF-Conventions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'source': 'C:\\\\Users\\\\Norman\\\\.cate\\\\data_stores\\\\local\\\\local.esacci.SEALEVEL.mon.IND.MSLAMPH.multi-sensor.multi-platform.MERGED.2-0.r1.6ba656f9-7c90-3b15-aad2-c137f8b61909\\\\ESACCI-SEALEVEL-IND-MSLAMPH-MERGED-20161202000000-fv02.nc',\n",
       " 'original_shape': (276,),\n",
       " 'dtype': dtype('float32'),\n",
       " 'units': 'days since 1950-01-01'}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds.time_step.encoding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<xarray.Dataset>\n",
       "Dimensions:    (bnds: 2, lat: 720, lon: 1440, period: 2, time: 1, time_step: 276)\n",
       "Coordinates:\n",
       "  * time_step  (time_step) datetime64[ns] 1993-01-15 1993-02-15 1993-03-15 ...\n",
       "  * period     (period) float32 1.0 0.5\n",
       "  * lat        (lat) float32 -89.875 -89.625 -89.375 -89.125 -88.875 -88.625 ...\n",
       "  * lon        (lon) float32 0.125 0.375 0.625 0.875 1.125 1.375 1.625 1.875 ...\n",
       "  * time       (time) datetime64[ns] 2004-06-30T12:00:00\n",
       "    time_bnds  (time, bnds) datetime64[ns] 1993-01-15 2015-12-15\n",
       "Dimensions without coordinates: bnds\n",
       "Data variables:\n",
       "    ampl       (lat, lon, period) float32 ...\n",
       "    phase      (lat, lon, period) float32 ...\n",
       "Attributes:\n",
       "    title:                      Mean Sea Level changes amplitude and phases\n",
       "    institution:                ESA, CLS, CNES\n",
       "    references:                 http://www.esa-sealevel-cci.org/products\n",
       "    tracking_id:                \n",
       "    source:                     ERS-1 Phase C OPR V6, ERS-1 Phase E OPR V3, E...\n",
       "    platform:                   ERS-1, ERS-2, ENVISAT, TOPEX/Poseidon, Jason-...\n",
       "    sensor:                     RA, RA2, Poseidon-1, Poseidon-2, Poseidon-3, ...\n",
       "    Conventions:                CF-1.6\n",
       "    product_version:            2.0\n",
       "    summary:                    This dataset contains global maps of mean sea...\n",
       "    keywords:                   altimetry\n",
       "    id:                         GLO-MSL-AMPH-MERGED\n",
       "    naming_authority:           ESA CCI\n",
       "    keywords_vocabulary:        NetCDF COARDS Climate and Forecast Standard N...\n",
       "    standard_name_vocabulary:   NetCDF Climate and Forecast (CF) Metadata Con...\n",
       "    cdm_data_type:              Grid\n",
       "    comment:                    These data were produced at CLS as part of th...\n",
       "    license:                    ESA CCI Data Policy: free and open access.\n",
       "    date_created:               2016-12-02 00:00:00\n",
       "    history:                    2016-12-02 00:00:00 : creation\n",
       "    contact:                    info-sealevel@esa-sealevel-cci.org\n",
       "    project:                    Climate Change Initiative - European Space Ag...\n",
       "    creator_name:               ESA, CLS\n",
       "    creator_url:                http://www.esa-sealevel-cci.org/\n",
       "    creator_email:              info-sealevel@esa-sealevel-cci.org\n",
       "    geospatial_lat_min:         -89.875\n",
       "    geospatial_lat_max:         89.875\n",
       "    geospatial_lon_min:         0.125\n",
       "    geospatial_lon_max:         359.875\n",
       "    geospatial_vertical_min:    0.0\n",
       "    geospatial_vertical_max:    0.0\n",
       "    geospatial_lat_units:       degrees_north\n",
       "    geospatial_lon_units:       degrees_east\n",
       "    geospatial_lat_resolution:  0.25\n",
       "    geospatial_lon_resolution:  0.25\n",
       "    time_coverage_start:        1993-01-01 00:00:00\n",
       "    time_coverage_end:          2015-12-31 23:59:59\n",
       "    time_coverage_duration:     P23Y\n",
       "    time_coverage_resolution:   P1M"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Time encoding properties\n",
    "dtype = ds.time_step.encoding['dtype']\n",
    "units = ds.time_step.encoding['units']\n",
    "\n",
    "# Get the time boundary values\n",
    "ts       = ds.time_step.values\n",
    "ts_start = ts[0]\n",
    "ts_end   = ts[-1]\n",
    "ts_mid   = ts_start + 0.5 * (ts_end - ts_start)\n",
    "\n",
    "# New coordinate variables according to CF\n",
    "time      = xr.DataArray(np.array([ts_mid]), dims='time')\n",
    "time_bnds = xr.DataArray(np.array([[ts_start, ts_end]]), dims=['time', 'bnds'])\n",
    "\n",
    "# Assign coordinate variables\n",
    "ds = ds.assign_coords(time=time, time_bnds=time_bnds)\n",
    "\n",
    "# Update coordinate variable attributes according to CF\n",
    "ds.time.attrs.update(bounds='time_bnds')\n",
    "\n",
    "# Set coordinate variable encodings\n",
    "ds.time.encoding.update(units=units, dtype=dtype)\n",
    "ds.time_bnds.encoding.update(units=units, dtype=dtype)\n",
    "\n",
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "Then we insert a time axis of size one into the data variables using the [xarray](http://xarray.pydata.org) [DataArray](http://xarray.pydata.org/en/stable/data-structures.html#dataarray) method [expand_dims()](http://xarray.pydata.org/en/stable/generated/xarray.DataArray.expand_dims.html), so we can later easily concatenate multiple Sea-Level datasets along the time dimension."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<xarray.Dataset>\n",
       "Dimensions:    (bnds: 2, lat: 720, lon: 1440, period: 2, time: 1, time_step: 276)\n",
       "Coordinates:\n",
       "  * time       (time) datetime64[ns] 2004-06-30T12:00:00\n",
       "  * time_step  (time_step) datetime64[ns] 1993-01-15 1993-02-15 1993-03-15 ...\n",
       "  * period     (period) float32 1.0 0.5\n",
       "  * lat        (lat) float32 -89.875 -89.625 -89.375 -89.125 -88.875 -88.625 ...\n",
       "  * lon        (lon) float32 0.125 0.375 0.625 0.875 1.125 1.375 1.625 1.875 ...\n",
       "    time_bnds  (time, bnds) datetime64[ns] 1993-01-15 2015-12-15\n",
       "Dimensions without coordinates: bnds\n",
       "Data variables:\n",
       "    ampl       (time, lat, lon, period) float32 nan nan nan nan nan nan nan ...\n",
       "    phase      (time, lat, lon, period) float32 nan nan nan nan nan nan nan ...\n",
       "Attributes:\n",
       "    title:                      Mean Sea Level changes amplitude and phases\n",
       "    institution:                ESA, CLS, CNES\n",
       "    references:                 http://www.esa-sealevel-cci.org/products\n",
       "    tracking_id:                \n",
       "    source:                     ERS-1 Phase C OPR V6, ERS-1 Phase E OPR V3, E...\n",
       "    platform:                   ERS-1, ERS-2, ENVISAT, TOPEX/Poseidon, Jason-...\n",
       "    sensor:                     RA, RA2, Poseidon-1, Poseidon-2, Poseidon-3, ...\n",
       "    Conventions:                CF-1.6\n",
       "    product_version:            2.0\n",
       "    summary:                    This dataset contains global maps of mean sea...\n",
       "    keywords:                   altimetry\n",
       "    id:                         GLO-MSL-AMPH-MERGED\n",
       "    naming_authority:           ESA CCI\n",
       "    keywords_vocabulary:        NetCDF COARDS Climate and Forecast Standard N...\n",
       "    standard_name_vocabulary:   NetCDF Climate and Forecast (CF) Metadata Con...\n",
       "    cdm_data_type:              Grid\n",
       "    comment:                    These data were produced at CLS as part of th...\n",
       "    license:                    ESA CCI Data Policy: free and open access.\n",
       "    date_created:               2016-12-02 00:00:00\n",
       "    history:                    2016-12-02 00:00:00 : creation\n",
       "    contact:                    info-sealevel@esa-sealevel-cci.org\n",
       "    project:                    Climate Change Initiative - European Space Ag...\n",
       "    creator_name:               ESA, CLS\n",
       "    creator_url:                http://www.esa-sealevel-cci.org/\n",
       "    creator_email:              info-sealevel@esa-sealevel-cci.org\n",
       "    geospatial_lat_min:         -89.875\n",
       "    geospatial_lat_max:         89.875\n",
       "    geospatial_lon_min:         0.125\n",
       "    geospatial_lon_max:         359.875\n",
       "    geospatial_vertical_min:    0.0\n",
       "    geospatial_vertical_max:    0.0\n",
       "    geospatial_lat_units:       degrees_north\n",
       "    geospatial_lon_units:       degrees_east\n",
       "    geospatial_lat_resolution:  0.25\n",
       "    geospatial_lon_resolution:  0.25\n",
       "    time_coverage_start:        1993-01-01 00:00:00\n",
       "    time_coverage_end:          2015-12-31 23:59:59\n",
       "    time_coverage_duration:     P23Y\n",
       "    time_coverage_resolution:   P1M"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds['ampl'] = ds.ampl.expand_dims('time')\n",
    "ds['phase'] = ds.phase.expand_dims('time')\n",
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "We now address the 1st issue by changing the order of the data variables' dimensions so that Cate can display them. We use the [xarray](http://xarray.pydata.org) [Dataset](http://xarray.pydata.org/en/stable/data-structures.html#dataset) method [transpose()](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.transpose.html):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<xarray.Dataset>\n",
       "Dimensions:    (bnds: 2, lat: 720, lon: 1440, period: 2, time: 1, time_step: 276)\n",
       "Coordinates:\n",
       "  * time       (time) datetime64[ns] 2004-06-30T12:00:00\n",
       "  * time_step  (time_step) datetime64[ns] 1993-01-15 1993-02-15 1993-03-15 ...\n",
       "  * period     (period) float32 1.0 0.5\n",
       "  * lat        (lat) float32 -89.875 -89.625 -89.375 -89.125 -88.875 -88.625 ...\n",
       "  * lon        (lon) float32 0.125 0.375 0.625 0.875 1.125 1.375 1.625 1.875 ...\n",
       "    time_bnds  (time, bnds) datetime64[ns] 1993-01-15 2015-12-15\n",
       "Dimensions without coordinates: bnds\n",
       "Data variables:\n",
       "    ampl       (time, period, lat, lon) float32 nan nan nan nan nan nan nan ...\n",
       "    phase      (time, period, lat, lon) float32 nan nan nan nan nan nan nan ...\n",
       "Attributes:\n",
       "    title:                      Mean Sea Level changes amplitude and phases\n",
       "    institution:                ESA, CLS, CNES\n",
       "    references:                 http://www.esa-sealevel-cci.org/products\n",
       "    tracking_id:                \n",
       "    source:                     ERS-1 Phase C OPR V6, ERS-1 Phase E OPR V3, E...\n",
       "    platform:                   ERS-1, ERS-2, ENVISAT, TOPEX/Poseidon, Jason-...\n",
       "    sensor:                     RA, RA2, Poseidon-1, Poseidon-2, Poseidon-3, ...\n",
       "    Conventions:                CF-1.6\n",
       "    product_version:            2.0\n",
       "    summary:                    This dataset contains global maps of mean sea...\n",
       "    keywords:                   altimetry\n",
       "    id:                         GLO-MSL-AMPH-MERGED\n",
       "    naming_authority:           ESA CCI\n",
       "    keywords_vocabulary:        NetCDF COARDS Climate and Forecast Standard N...\n",
       "    standard_name_vocabulary:   NetCDF Climate and Forecast (CF) Metadata Con...\n",
       "    cdm_data_type:              Grid\n",
       "    comment:                    These data were produced at CLS as part of th...\n",
       "    license:                    ESA CCI Data Policy: free and open access.\n",
       "    date_created:               2016-12-02 00:00:00\n",
       "    history:                    2016-12-02 00:00:00 : creation\n",
       "    contact:                    info-sealevel@esa-sealevel-cci.org\n",
       "    project:                    Climate Change Initiative - European Space Ag...\n",
       "    creator_name:               ESA, CLS\n",
       "    creator_url:                http://www.esa-sealevel-cci.org/\n",
       "    creator_email:              info-sealevel@esa-sealevel-cci.org\n",
       "    geospatial_lat_min:         -89.875\n",
       "    geospatial_lat_max:         89.875\n",
       "    geospatial_lon_min:         0.125\n",
       "    geospatial_lon_max:         359.875\n",
       "    geospatial_vertical_min:    0.0\n",
       "    geospatial_vertical_max:    0.0\n",
       "    geospatial_lat_units:       degrees_north\n",
       "    geospatial_lon_units:       degrees_east\n",
       "    geospatial_lat_resolution:  0.25\n",
       "    geospatial_lon_resolution:  0.25\n",
       "    time_coverage_start:        1993-01-01 00:00:00\n",
       "    time_coverage_end:          2015-12-31 23:59:59\n",
       "    time_coverage_duration:     P23Y\n",
       "    time_coverage_resolution:   P1M"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ds = ds.transpose('time', 'bnds', 'time_step', 'period', 'lat', 'lon')\n",
    "ds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "Finally we write the modified dataset as a new NetCDF file using the [xarray](http://xarray.pydata.org) [Dataset](http://xarray.pydata.org/en/stable/data-structures.html#dataset) method [to_netcdf()](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.to_netcdf.html):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "ds.to_netcdf('ESACCI-SEALEVEL-IND-MSLAMPH-MERGED-20161202000000-fv02-Cate.nc')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
